const express = require('express');
const path = require('path');
const fs = require('fs');
const cors = require('cors');
const session = require('express-session');
const { loadConfig, saveConfig, validateAuth, generateId } = require('./config/config');

const app = express();
const PORT = 3001;

// 启用CORS以允许跨域访问
app.use(cors());

// 解析JSON请求体
app.use(express.json());

// 会话管理
app.use(session({
    secret: 'apk-express-secret-key',
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 24 * 60 * 60 * 1000 } // 24小时
}));

// 添加服务器端日志函数
function log(message, data = null) {
    const timestamp = new Date().toLocaleString('zh-CN');
    if (data) {
        console.log(`[${timestamp}] ${message}:`, data);
    } else {
        console.log(`[${timestamp}] ${message}`);
    }
}

// 添加请求日志中间件
app.use((req, res, next) => {
    const timestamp = new Date().toLocaleString('zh-CN');
    console.log(`[${timestamp}] ${req.method} ${req.url} - ${req.ip}`);

    // 监听响应完成
    res.on('finish', () => {
        console.log(`[${timestamp}] ${req.method} ${req.url} - ${res.statusCode} ${res.statusMessage}`);
    });

    next();
});

// 静态文件服务中间件 - 服务public目录
app.use('/css', express.static(path.join(__dirname, 'public/css')));
app.use('/js', express.static(path.join(__dirname, 'public/js')));

// 创建文件ID到路径的映射
let filePathMap = new Map();

// 更新文件路径映射
function updateFilePathMap() {
    filePathMap.clear();
    const allApks = findApkFiles();
    allApks.forEach(apk => {
        filePathMap.set(apk.fileId, apk.path);
    });
    log(`更新文件路径映射，共 ${filePathMap.size} 个文件`);
}

// 修改静态文件服务中间件
app.use((req, res, next) => {
    // 处理APK文件下载请求
    if (req.url.startsWith('/download/')) {
        const fileId = req.url.replace('/download/', '');
        log(`APK下载请求 - 文件ID: ${fileId.substring(0, 8)}...`);

        // 确保文件路径映射是最新的
        updateFilePathMap();

        const filePath = filePathMap.get(fileId);

        if (!filePath) {
            log(`未找到文件ID对应的路径: ${fileId.substring(0, 8)}...`);
            res.status(404).send('文件未找到');
            return;
        }

        log(`解析文件路径: ${filePath}`);

        // 检查文件是否存在
        fs.access(filePath, fs.constants.F_OK, (err) => {
            if (err) {
                log(`文件不存在: ${filePath}`, err.message);
                res.status(404).send('文件不存在');
                return;
            }

            // 检查是否可读
            fs.access(filePath, fs.constants.R_OK, (readErr) => {
                if (readErr) {
                    log(`文件无读取权限: ${filePath}`, readErr.message);
                    res.status(403).send('文件无读取权限');
                    return;
                }

                log(`文件存在且可读: ${filePath}`);

                // 获取文件信息
                fs.stat(filePath, (statErr, stats) => {
                    if (statErr) {
                        log(`获取文件信息失败`, statErr.message);
                        res.status(500).send('获取文件信息失败');
                        return;
                    }

                    // 提取原始文件名
                    const originalFileName = path.basename(filePath);

                    log(`文件信息`, {
                        fileName: originalFileName,
                        size: `${(stats.size / 1024 / 1024).toFixed(2)} MB`,
                        modified: stats.mtime.toLocaleString('zh-CN'),
                        isFile: stats.isFile()
                    });

                    // 设置正确的响应头 - 修复文件名问题
                    res.setHeader('Content-Type', 'application/vnd.android.package-archive');
                    res.setHeader('Content-Length', stats.size);

                    // 修复文件名编码问题
                    const encodedFileName = encodeURIComponent(originalFileName);
                    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodedFileName}; filename="${originalFileName}"`);

                    // 添加缓存控制
                    res.setHeader('Cache-Control', 'no-cache');
                    res.setHeader('Pragma', 'no-cache');

                    log(`开始下载文件: ${originalFileName}`);

                    // 发送文件
                    const stream = fs.createReadStream(filePath);

                    stream.on('error', (streamErr) => {
                        log(`文件流错误`, streamErr.message);
                        if (!res.headersSent) {
                            res.status(500).send('文件读取失败');
                        }
                    });

                    stream.on('end', () => {
                        log(`文件下载完成: ${originalFileName}`);
                    });

                    // 监听下载进度（可选）
                    let downloaded = 0;
                    stream.on('data', (chunk) => {
                        downloaded += chunk.length;
                        const progress = ((downloaded / stats.size) * 100).toFixed(1);
                        // 每传输10MB记录一次进度
                        if (downloaded % (10 * 1024 * 1024) < chunk.length) {
                            log(`下载进度: ${originalFileName} - ${progress}%`);
                        }
                    });

                    stream.pipe(res);
                });
            });
        });

        return;
    }

    // 如果请求的是APK文件（旧方式兼容）
    if (req.url.toLowerCase().endsWith('.apk')) {
        const filePath = path.join(process.cwd(), req.url);
        log(`APK文件请求（旧方式）: ${req.url}`);
        log(`解析文件路径: ${filePath}`);

        // 检查文件是否存在
        fs.access(filePath, fs.constants.F_OK, (err) => {
            if (err) {
                log(`文件不存在: ${filePath}`, err.message);

                // 尝试查找实际的APK文件位置
                log(`开始搜索APK文件: ${path.basename(req.url)}`);
                findApkFileByName(path.basename(req.url))
                    .then(foundPath => {
                        if (foundPath) {
                            log(`找到APK文件: ${foundPath}`);
                            res.download(foundPath, path.basename(req.url), (downloadErr) => {
                                if (downloadErr) {
                                    log(`下载失败`, downloadErr.message);
                                    res.status(500).send('下载失败');
                                } else {
                                    log(`下载成功: ${foundPath}`);
                                }
                            });
                        } else {
                            log(`未找到APK文件: ${path.basename(req.url)}`);
                            res.status(404).send('文件未找到');
                        }
                    })
                    .catch(searchErr => {
                        log(`搜索APK文件时出错`, searchErr.message);
                        res.status(500).send('搜索文件失败');
                    });
                return;
            }

            // 文件存在，使用express的download方法
            res.download(filePath, path.basename(req.url), (downloadErr) => {
                if (downloadErr) {
                    log(`下载过程中出错`, downloadErr.message);
                    if (!res.headersSent) {
                        res.status(500).send('下载失败');
                    }
                } else {
                    log(`文件下载完成: ${filePath}`);
                }
            });
        });
    } else {
        // 非APK文件，使用默认静态文件服务
        express.static('.')(req, res, next);
    }
});

// 根据文件名搜索APK文件
async function findApkFileByName(fileName) {
    log(`搜索APK文件: ${fileName}`);

    try {
        const config = loadConfig();

        for (const packager of config.packagers) {
            if (!packager.enabled) continue;

            log(`在打包机中搜索: ${packager.name} (${packager.path})`);

            try {
                const foundPath = await searchInDirectory(packager.path, fileName);
                if (foundPath) {
                    log(`在打包机 ${packager.name} 中找到文件: ${foundPath}`);
                    return foundPath;
                }
            } catch (err) {
                log(`搜索打包机 ${packager.name} 时出错`, err.message);
            }
        }

        log(`未在任何打包机中找到文件: ${fileName}`);
        return null;
    } catch (err) {
        log(`搜索过程中出错`, err.message);
        return null;
    }
}

// 在目录中递归搜索文件
function searchInDirectory(dir, fileName) {
    return new Promise((resolve, reject) => {
        function search(currentDir) {
            try {
                const files = fs.readdirSync(currentDir);

                for (const file of files) {
                    const fullPath = path.join(currentDir, file);
                    const stat = fs.statSync(fullPath);

                    if (stat.isFile() && file === fileName) {
                        resolve(fullPath);
                        return;
                    }

                    if (stat.isDirectory() && !file.startsWith('.') &&
                        file !== 'node_modules' && file !== 'public') {
                        const result = search(fullPath);
                        if (result) return result;
                    }
                }
            } catch (err) {
                log(`搜索目录 ${currentDir} 时出错`, err.message);
            }
        }

        const result = search(dir);
        if (!result) {
            resolve(null);
        }
    });
}

// 页面认证中间件（专门用于管理页面）
function requirePageAuth(req, res, next) {
    if (req.session && req.session.authenticated) {
        next();
    } else {
        res.redirect('/login');
    }
}

// API认证中间件（专门用于API接口）
function requireApiAuth(req, res, next) {
    if (req.session && req.session.authenticated) {
        next();
    } else {
        res.status(401).json({ success: false, message: '未授权访问' });
    }
}

// 获取本机IP地址（优化后的版本）
function getLocalIP() {
    const { networkInterfaces } = require('os');
    const nets = networkInterfaces();
    const results = [];

    for (const name of Object.keys(nets)) {
        for (const net of nets[name]) {
            // 跳过非IPv4和内部地址
            if (net.family === 'IPv4' && !net.internal) {
                results.push({
                    address: net.address,
                    interface: name
                });
            }
        }
    }

    // 优先返回局域网IP地址（192.168.x.x, 10.x.x.x, 172.16-31.x.x）
    const localNetworks = results.filter(item => {
        const ip = item.address;
        return ip.startsWith('192.168.') ||
            ip.startsWith('10.') ||
            (ip.startsWith('172.') &&
                parseInt(ip.split('.')[1]) >= 16 &&
                parseInt(ip.split('.')[1]) <= 31);
    });

    // 如果找到局域网IP，优先返回
    if (localNetworks.length > 0) {
        console.log('🔍 发现的局域网IP地址:');
        localNetworks.forEach(item => {
            console.log(`   - ${item.address} (${item.interface})`);
        });
        return localNetworks[0].address;
    }

    // 如果没有找到局域网IP，返回第一个可用的IP
    if (results.length > 0) {
        console.log('⚠️  未找到标准局域网IP，使用第一个可用IP:');
        results.forEach(item => {
            console.log(`   - ${item.address} (${item.interface})`);
        });
        return results[0].address;
    }

    return 'localhost';
}

// 递归扫描目录找到所有APK文件（支持多个路径）- 增强版
function findApkFiles() {
    const config = loadConfig();
    const allApkFiles = [];

    config.packagers.forEach(packager => {
        if (!packager.enabled) return;

        try {
            log(`扫描打包机: ${packager.name} (${packager.path})`);
            const apkFiles = scanDirectoryWithFolders(packager.path, packager);
            log(`${packager.name} 找到 ${apkFiles.length} 个APK文件`);
            allApkFiles.push(...apkFiles);
        } catch (err) {
            log(`无法扫描 ${packager.name} (${packager.path})`, err.message);
        }
    });

    // 按创建时间排序（最新的在前面）
    const sortedFiles = allApkFiles.sort((a, b) => new Date(b.lastModifiedTime) - new Date(a.lastModifiedTime));
    log(`总共找到 ${sortedFiles.length} 个APK文件`);

    return sortedFiles;
}

// 扫描目录并记录文件夹信息 - 修复网络路径问题
function scanDirectoryWithFolders(dir, packager, basePath = dir, apkFiles = []) {
    try {
        const files = fs.readdirSync(dir);

        files.forEach(file => {
            const fullPath = path.join(dir, file);
            const stat = fs.statSync(fullPath);

            if (stat.isDirectory() && !file.startsWith('.') && file !== 'node_modules' && file !== 'public') {
                scanDirectoryWithFolders(fullPath, packager, basePath, apkFiles);
            } else if (path.extname(file).toLowerCase() === '.apk') {
                const relativePath = path.relative(basePath, fullPath);
                const folderPath = path.dirname(relativePath);

                // 生成唯一的文件ID用于下载
                const fileId = Buffer.from(fullPath).toString('base64').replace(/[+/=]/g, '');

                const apkInfo = {
                    name: file,
                    path: fullPath,
                    fileId: fileId, // 添加文件ID
                    relativePath: path.relative('.', fullPath),
                    size: (stat.size / 1024 / 1024).toFixed(2) + ' MB',
                    sizeBytes: stat.size,
                    lastModified: stat.mtime.toLocaleString('zh-CN'),
                    lastModifiedTime: stat.mtime.toISOString(),
                    createdTime: stat.birthtime.toISOString(),
                    source: packager.name,
                    sourceType: packager.type,
                    packagerId: packager.id,
                    folderPath: folderPath === '.' ? '' : folderPath.replace(/\\/g, '/'),
                    folderName: folderPath === '.' ? '根目录' : folderPath,
                    fullFolderPath: folderPath === '.' ? packager.path : path.join(packager.path, folderPath)
                };

                log(`找到APK: ${apkInfo.name} (${apkInfo.size}) - ID: ${fileId.substring(0, 8)}...`);
                apkFiles.push(apkInfo);
            }
        });
    } catch (err) {
        throw err;
    }

    return apkFiles;
}

// 构建文件夹树结构 - 修复路径分隔符
function buildFolderTree(apks, packager) {
    const tree = {
        path: '',
        name: '根目录',
        children: {},
        apkCount: 0,
        level: 0
    };

    // 先收集所有路径
    const pathSet = new Set();
    apks.forEach(apk => {
        const folderPath = apk.folderPath || '';
        if (folderPath) {
            // 添加所有父路径
            const parts = folderPath.split(/[\/\\]/).filter(p => p);
            for (let i = 0; i < parts.length; i++) {
                const partialPath = parts.slice(0, i + 1).join('/');
                pathSet.add(partialPath);
            }
        }
        pathSet.add(folderPath);
    });

    // 构建树结构
    const sortedPaths = Array.from(pathSet).sort();

    sortedPaths.forEach(folderPath => {
        if (!folderPath) {
            // 根目录APK
            tree.apkCount = apks.filter(apk => !apk.folderPath).length;
            return;
        }

        const parts = folderPath.split('/');
        let currentNode = tree;

        parts.forEach((part, index) => {
            const currentPath = parts.slice(0, index + 1).join('/');

            if (!currentNode.children[part]) {
                // 构建正确的完整路径，使用反斜杠
                const windowsPath = currentPath.replace(/\//g, '\\');
                const fullPath = packager.path + (packager.path.endsWith('\\') ? '' : '\\') + windowsPath;

                currentNode.children[part] = {
                    path: currentPath,
                    name: part,
                    fullPath: fullPath,
                    children: {},
                    apkCount: 0,
                    level: index + 1
                };
            }

            currentNode = currentNode.children[part];
        });

        // 计算当前文件夹的APK数量
        currentNode.apkCount = apks.filter(apk => apk.folderPath === folderPath).length;
    });

    return tree;
}

// 获取打包机树结构 - 树形结构版
function getPackagerTree() {
    const config = loadConfig();
    const allApks = findApkFiles();

    return config.packagers.map(packager => {
        const packagerApks = allApks.filter(apk => apk.packagerId === packager.id);

        // 构建文件夹树结构
        const folderTree = buildFolderTree(packagerApks, packager);

        return {
            id: packager.id,
            name: packager.name,
            path: packager.path,
            type: packager.type,
            enabled: packager.enabled,
            totalApks: packagerApks.length,
            folderTree: folderTree
        };
    });
}

// 将树结构转换为扁平列表用于前端显示
function flattenFolderTree(node, result = [], parentExpanded = true) {
    if (node.path !== '' || node.name === '根目录') {
        result.push({
            path: node.path,
            name: node.name,
            fullPath: node.fullPath,
            apkCount: node.apkCount,
            level: node.level,
            hasChildren: Object.keys(node.children).length > 0,
            parentExpanded: parentExpanded
        });
    }

    // 按名称排序子文件夹
    const sortedChildren = Object.values(node.children).sort((a, b) =>
        a.name.localeCompare(b.name)
    );

    sortedChildren.forEach(child => {
        flattenFolderTree(child, result, parentExpanded);
    });

    return result;
}

// 读取HTML模板
function getHTMLTemplate(templateName) {
    try {
        const templatePath = path.join(__dirname, 'public/views', `${templateName}.html`);
        return fs.readFileSync(templatePath, 'utf8');
    } catch (err) {
        console.error(`无法读取模板 ${templateName}:`, err.message);
        return null;
    }
}

// === 路由定义 ===

// 主页路由 - 修改为显示首页专用APK
app.get('/', (req, res) => {
    const homepageApks = getHomepageApkFiles();
    const template = getHTMLTemplate('index');
    if (!template) {
        return res.status(500).send('模板文件不存在');
    }

    // 替换模板变量
    const html = template
        .replace('{{SERVER_URL}}', `http://${getLocalIP()}:${PORT}`)
        .replace('{{SERVER_DIR}}', process.cwd())
        .replace('{{START_TIME}}', new Date().toLocaleString('zh-CN'))
        .replace('{{CONTENT}}', generateHomepageAPKListHTML(homepageApks)); // 使用新的HTML生成函数

    res.send(html);
});

// 登录页面
app.get('/login', (req, res) => {
    // 如果已经登录，重定向到管理页面
    if (req.session && req.session.authenticated) {
        return res.redirect('/admin');
    }

    const template = getHTMLTemplate('login');
    if (!template) {
        return res.status(500).send('登录页面模板不存在');
    }
    res.send(template);
});

// 管理页面 - 使用页面认证中间件
app.get('/admin', requirePageAuth, (req, res) => {
    const template = getHTMLTemplate('admin');
    if (!template) {
        return res.status(500).send('管理页面模板不存在');
    }
    res.send(template);
});

// === API 路由 ===

// 获取打包机树结构API
app.get('/api/packager-tree', (req, res) => {
    try {
        const tree = getPackagerTree();
        res.json({ success: true, data: tree });
    } catch (err) {
        console.error('获取打包机树失败:', err);
        res.json({ success: false, message: '获取打包机结构失败' });
    }
});

// 新增API：获取首页APK列表
app.get('/api/homepage-apks', (req, res) => {
    try {
        const homepageApks = getHomepageApkFiles();
        res.json({
            success: true,
            data: homepageApks,
            server: `http://${getLocalIP()}:${PORT}`,
            timestamp: new Date().toISOString()
        });
    } catch (err) {
        console.error('获取首页APK列表失败:', err);
        res.json({ success: false, message: '获取首页APK列表失败' });
    }
});

// 新增API：获取打包机的扁平文件夹列表
app.get('/api/packager-folders/:packagerId', (req, res) => {
    try {
        const { packagerId } = req.params;
        const config = loadConfig();
        const packager = config.packagers.find(p => p.id === packagerId);

        if (!packager) {
            return res.json({ success: false, message: '打包机不存在' });
        }

        const allApks = findApkFiles();
        const packagerApks = allApks.filter(apk => apk.packagerId === packagerId);
        const folderTree = buildFolderTree(packagerApks, packager);
        const flatFolders = flattenFolderTree(folderTree);

        res.json({ success: true, data: flatFolders });
    } catch (err) {
        console.error('获取文件夹列表失败:', err);
        res.json({ success: false, message: '获取文件夹列表失败' });
    }
});

// 登录API
app.post('/api/auth/login', (req, res) => {
    const { username, password } = req.body;

    if (validateAuth(username, password)) {
        req.session.authenticated = true;
        req.session.username = username;
        res.json({ success: true, message: '登录成功' });
    } else {
        res.json({ success: false, message: '用户名或密码错误' });
    }
});

// 退出登录API
app.post('/api/auth/logout', (req, res) => {
    req.session.destroy((err) => {
        if (err) {
            res.json({ success: false, message: '退出登录失败' });
        } else {
            res.json({ success: true, message: '已退出登录' });
        }
    });
});

// 检查登录状态API
app.get('/api/auth/status', (req, res) => {
    if (req.session && req.session.authenticated) {
        res.json({
            success: true,
            authenticated: true,
            username: req.session.username
        });
    } else {
        res.json({
            success: true,
            authenticated: false
        });
    }
});

// 获取打包机列表 - 使用API认证中间件
app.get('/api/admin/packagers', requireApiAuth, (req, res) => {
    const config = loadConfig();
    res.json({ success: true, data: config.packagers });
});

// 添加打包机 - 使用API认证中间件
app.post('/api/admin/packagers', requireApiAuth, (req, res) => {
    const { name, path: packagerPath, type = 'network' } = req.body;

    if (!name || !packagerPath) {
        return res.json({ success: false, message: '名称和路径不能为空' });
    }

    const config = loadConfig();
    const newPackager = {
        id: generateId(),
        name,
        path: packagerPath,
        type,
        enabled: true
    };

    config.packagers.push(newPackager);

    if (saveConfig(config)) {
        res.json({ success: true, message: '打包机添加成功', data: newPackager });
    } else {
        res.json({ success: false, message: '保存配置失败' });
    }
});

// 切换打包机状态 - 使用API认证中间件
app.put('/api/admin/packagers/:id/toggle', requireApiAuth, (req, res) => {
    const { id } = req.params;
    const config = loadConfig();

    const packager = config.packagers.find(p => p.id === id);
    if (!packager) {
        return res.json({ success: false, message: '打包机不存在' });
    }

    packager.enabled = !packager.enabled;

    if (saveConfig(config)) {
        res.json({ success: true, message: '状态更新成功' });
    } else {
        res.json({ success: false, message: '保存配置失败' });
    }
});

// 删除打包机 - 使用API认证中间件
app.delete('/api/admin/packagers/:id', requireApiAuth, (req, res) => {
    const { id } = req.params;
    const config = loadConfig();

    const index = config.packagers.findIndex(p => p.id === id);
    if (index === -1) {
        return res.json({ success: false, message: '打包机不存在' });
    }

    config.packagers.splice(index, 1);

    if (saveConfig(config)) {
        res.json({ success: true, message: '删除成功' });
    } else {
        res.json({ success: false, message: '保存配置失败' });
    }
});

// API路由 - 获取APK文件列表（增强版）
app.get('/api/apks', (req, res) => {
    try {
        const apkFiles = findApkFiles();
        res.json({
            success: true,
            data: apkFiles,
            server: `http://${getLocalIP()}:${PORT}`,
            timestamp: new Date().toISOString()
        });
    } catch (err) {
        console.error('获取APK列表失败:', err);
        res.json({ success: false, message: '获取APK列表失败' });
    }
});

// 健康检查接口
app.get('/api/health', (req, res) => {
    res.json({
        status: 'ok',
        uptime: process.uptime(),
        timestamp: new Date().toISOString()
    });
});

// 启动服务器
app.listen(PORT, '0.0.0.0', () => {
    const localIP = getLocalIP();

    console.log('\n🚀 APK文件服务器已启动！');
    console.log('==================================');
    console.log(`📍 本地访问地址: http://localhost:${PORT}`);
    console.log(`🌐 局域网访问地址: http://${localIP}:${PORT}`);
    console.log(`⚙️ 管理地址: http://${localIP}:${PORT}/admin`);
    console.log(`📁 服务目录: ${process.cwd()}`);
    console.log('==================================');
    console.log('💡 提示:');
    console.log('   - 局域网内其他设备可通过IP地址访问');
    console.log('   - 管理员账号: admin / apk123456');
    console.log('   - 按 Ctrl+C 停止服务器');
    console.log('==================================\n');

    // 自动扫描APK文件
    const apkFiles = findApkFiles();
    console.log(`📦 发现 ${apkFiles.length} 个APK文件:`);

    // 按打包机分组显示
    const packagerTree = getPackagerTree();
    packagerTree.forEach(packager => {
        console.log(`   📱 ${packager.name}: ${packager.totalApks} 个文件`);
    });
    console.log('');
});

// 优雅关闭
process.on('SIGINT', () => {
    console.log('\n👋 正在关闭服务器...');
    process.exit(0);
});

// 排除规则：目录名为 Apk9.9.9（大小写不敏感），任意层级均排除
const EXCLUDED_DIR_NAME = 'Apk9.9.9';
function isExcludedPath(folderPath) {
    if (!folderPath) return false;

    // 添加调试日志
    log(`检查排除路径: ${folderPath}`);

    const segments = folderPath.split(/[\\/]/).filter(Boolean);
    log(`路径分段: ${JSON.stringify(segments)}`);

    const shouldExclude = segments.some(seg => {
        const isMatch = seg.toLowerCase() === EXCLUDED_DIR_NAME.toLowerCase();
        if (isMatch) {
            log(`找到匹配的排除目录: ${seg}`);
        }
        return isMatch;
    });

    log(`路径 "${folderPath}" 排除结果: ${shouldExclude}`);
    return shouldExclude;
}

// 首页：每个一级子目录取最新包，但排除任意层级包含 Apk9.9.9 的目录
function getHomepageApkFiles() {
    const config = loadConfig();
    const homepageApks = [];

    log(`开始获取首页APK文件...`);

    config.packagers.forEach(packager => {
        if (!packager.enabled) return;

        try {
            log(`处理打包机: ${packager.name} (${packager.path})`);
            const allApks = scanDirectoryWithFolders(packager.path, packager); // apk.folderPath 形如 'A/B/C'
            log(`打包机 ${packager.name} 扫描到 ${allApks.length} 个APK文件`);

            const firstLevelMap = new Map();
            let excludedCount = 0;

            allApks.forEach(apk => {
                const fp = apk.folderPath || '';
                if (!fp) {
                    log(`跳过根目录APK: ${apk.name}`);
                    return;
                }

                // 检查排除路径
                const excluded = isExcludedPath(fp);
                if (excluded) {
                    excludedCount++;
                    log(`排除APK: ${apk.name}, 路径: ${fp} (包含排除目录)`);
                    return;
                }

                const firstLevel = fp.split('/')[0].trim();
                if (!firstLevel) {
                    log(`跳过无效一级目录APK: ${apk.name}`);
                    return;
                }

                if (!firstLevelMap.has(firstLevel)) firstLevelMap.set(firstLevel, []);
                firstLevelMap.get(firstLevel).push(apk);
                log(`添加APK到一级目录 ${firstLevel}: ${apk.name}`);
            });

            log(`打包机 ${packager.name} 排除了 ${excludedCount} 个APK文件`);
            log(`打包机 ${packager.name} 有 ${firstLevelMap.size} 个一级目录`);

            firstLevelMap.forEach((apks, dirName) => {
                apks.sort((a, b) => new Date(b.lastModifiedTime) - new Date(a.lastModifiedTime));
                const latest = { ...apks[0], firstLevelDir: dirName, totalInDir: apks.length };
                homepageApks.push(latest);
                log(`添加一级目录 ${dirName} 的最新APK: ${latest.name}`);
            });
        } catch (e) {
            log(`首页聚合失败: ${packager.name}`, e.message);
        }
    });

    log(`首页总共聚合了 ${homepageApks.length} 个APK文件`);
    return homepageApks.sort((a, b) => new Date(b.lastModifiedTime) - new Date(a.lastModifiedTime));
}

// 生成首页APK文件列表HTML - 专门版本
function generateHomepageAPKListHTML(apkFiles) {
    if (apkFiles.length === 0) {
        return `
        <div class="no-files">
            😅 未找到任何项目的APK文件<br>
            请确保打包机配置正确且包含项目文件夹
        </div>`;
    }

    return `
    <div class="homepage-info">
        <p>📱 显示各项目最新版本，共 ${apkFiles.length} 个项目</p>
    </div>
    <div class="apk-grid">
        ${apkFiles.map(apk => {
        const downloadPath = `/download/${apk.fileId}`;
        return `
                <div class="apk-card homepage-card">
                    <div class="project-badge">${apk.firstLevelDir}</div>
                    <div class="apk-name">📱 ${apk.name}</div>
                    <div class="apk-info">
                        📦 大小: ${apk.size}<br>
                        🕒 修改时间: ${apk.lastModified}<br>
                        📂 项目: ${apk.firstLevelDir}<br>
                        📊 项目内APK: ${apk.totalInDir} 个<br>
                        🏷️ 来源: ${apk.source || '未知'} (${apk.sourceType === 'network' ? '网络' : '本地'})
                    </div>
                    <div class="card-actions">
                        <a href="${downloadPath}" 
                           class="download-btn latest-btn" 
                           download="${apk.name}"
                           title="下载 ${apk.name}">
                            ⬇️ 下载最新版
                        </a>
                        <button class="view-all-btn" onclick="viewProjectFiles('${apk.packagerId}', '${apk.firstLevelDir}')">
                            📋 查看全部
                        </button>
                    </div>
                </div>
            `;
    }).join('')}
    </div>`;
}